// Learn TypeScript:
//  - https://docs.cocos.com/creator/2.4/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/2.4/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/2.4/manual/en/scripting/life-cycle-callbacks.html

const { ccclass, property } = cc._decorator;

@ccclass
export default class PoolManager extends cc.Component {

    @property([cc.Prefab])
    prefabList: cc.Prefab[] = [];

    poolList: Map<string, cc.NodePool>;
    private static _single: PoolManager;
    public static get single(): PoolManager {
        return PoolManager._single;
    }

    protected onLoad(): void {
        if (PoolManager._single == null) {
            PoolManager._single = this;
        } else {
            this.node.destroy();
            this.node.removeFromParent();
        }

        cc.game.addPersistRootNode(this.node);

        this.initNodePool();
    }

    private initNodePool() {
        this.poolList = new Map();
        for (const iterator of this.prefabList) {

            var nodePool = new cc.NodePool(iterator.name);
            for (let i = 0; i < 10; i++) {
                nodePool.put(cc.instantiate(iterator));
            }
            this.poolList.set(iterator.name, nodePool);
        }
    }
    public getPrefab(_name: string): cc.Prefab {
        for (const iterator of this.prefabList) {
            if (iterator.name == _name) {
                return iterator;
            }
        }
        return null;
    }

    public getNode(_name: string): cc.Node {
        var prefab = this.getPrefab(_name);
        if (prefab == null) {
            return null;
        }
        var nodePool = this.poolList.get(_name);
        if (nodePool == null) {
            return null;
        }
        if (nodePool.size() > 0) {
            return nodePool.get();
        } else {
            return cc.instantiate(prefab);
        }
    }

    public returnNode(_name: string, obj: cc.Node) {
        var nodePool = this.poolList.get(_name);
        if (nodePool != null) {
            nodePool.put(obj);
        }
    }
}
